//Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace Eas.WebCrawler.PlugIns.UrlProcessedHandlers {
    /// <summary>A helper class which attempts to determine if a web page was built with Asp.Net.</summary>
    /// <remarks>Please note that it is possible to build a page with ASP.Net but nto leave any tracks, so that we can not detect the use of ASP.Net.  We try to check as many things as possible, but in these cases the code acts like as if the page was NOT built with ASP.Net</remarks>
    public static class AspNetDetector {
        
        private static string AspDetectionRegex = "(\\s*<meta[^>]*content\\s*=\\s*\\\"Microsoft\\sVisual\\sStudio\\s\\.NET\\s7\\.1\\\"[^>]*\\>)|(\\s*<meta[^>]*content\\s*\\=\\s*\\\"Visual\\sBasic\\s7\\.0\\\"[^>]*\\>)|(\\s*<meta[^>]*content\\s*\\=\\s*\\\"C\\#\\\"[^>]*\\>)|(\\s*<meta[^>]*name\\s*\\=\\s*\\\"vs_defaultClientScript\\\"[^>]*\\>)|(\\s*<meta[^>]*name\\s*\\=\\s*\\\"vs_targetSchema\\\"[^>]*\\>)|(\\s*<input[^>]*id\\s*\\=\\s*\\\"__VIEWSTATE\\\")|(ms_positioning)";
        
        private const System.Text.RegularExpressions.RegexOptions PredefinedOptions =
                    System.Text.RegularExpressions.RegexOptions.Compiled |
                    System.Text.RegularExpressions.RegexOptions.CultureInvariant |
                    System.Text.RegularExpressions.RegexOptions.Multiline |
                    System.Text.RegularExpressions.RegexOptions.IgnoreCase;

        private static Stack<Regex> _CachedRegexes = new Stack<Regex>();
        private static Eas.WebCrawler.Common.Threading.SpinWaitLock _Lock = new Eas.WebCrawler.Common.Threading.SpinWaitLock();
        private static Regex GetRegex() {
            _Lock.Enter();
            try {
                if (_CachedRegexes.Count == 0)
                    return new System.Text.RegularExpressions.Regex(AspDetectionRegex, PredefinedOptions);
                else
                    return _CachedRegexes.Pop();
            }
            finally {
                _Lock.Exit();
            }
        }

        private static void ReturnRegex(Regex regex) {
            _CachedRegexes.Push(regex);
        }

        /// <summary>A function which checks if a page was built with ASP.Net ina way that ASP.Net could be detected.</summary>
        /// <param name="argument">Details of the processed page which we should check for the presence of ASP.Net</param>
        /// <returns><code>true</code> if we can detect that the page was built with ASP.Net, otherwise <code>false</code>.</returns>
        /// <remarks>Please note that it is possible to build a page with ASP.Net but nto leave any tracks, so that we can not detect the use of ASP.Net.  We try to check as many things as possible, but in these cases the code acts like as if the page was NOT built with ASP.Net</remarks>
        public static bool IsAspNet(Eas.WebCrawler.Interfaces.UrlCompletedEventArgs argument) {
            if (!argument.State.IsTextResponse) return false;
            if (argument.State.Request.Uri.AbsolutePath.EndsWith(".aspx", StringComparison.OrdinalIgnoreCase)) return true;

            string text;
            using (System.IO.TextReader reader = argument.Storage.GetTextReader()) {
                text = reader.ReadToEnd();
            }
            System.Text.RegularExpressions.Regex regex = GetRegex();
            try {
                return regex.IsMatch(text);
            }
            finally {
                ReturnRegex(regex);
            }
        }
    }
}
